
import { ZRenderComp } from '../../../common/component/zrComp';

import layout from './layout4';
import events from './events';

const PHASE_PAUSED = 0; // 暂停、未开始等
const PHASE_RUNNING = 1;
const PHASE_FINISHED = 2;

/**
 * 一个 Cable 类含 1 个核心 + 4 捆电缆.
 * 
 * zlevel : 10 (静态 + 动态)
 */
class Cables extends ZRenderComp {
	// param
	lastBreathTime = 0;

	constructor(args) {
		super(args.parent);
		const l = layout.cable;
		this.useParentZRenderInstance(l.coreX, l.coreY);

		this.cables = [
			{ playerNo: 2, factory: createCableLTPath, nameTagIndex: 1 },
			{ playerNo: 1, factory: createCableRTPath, nameTagIndex: 0 },
			{ playerNo: 4, factory: createCableLBPath, nameTagIndex: 3 },
			{ playerNo: 3, factory: createCableRBPath, nameTagIndex: 2 },
		].map(p => {
			let ln = layout.nameTags[p.nameTagIndex];
			let cable = new Cable({
				parent: this,
				coreWidth: l.coreWidth,
				coreX: 0,
				coreY: 0,
				tagX: ln.x - l.coreX,
				tagY: ln.y - l.coreY,
				tagHeight: ln.height,
				pathFactory: p.factory,
				playerNo: p.playerNo,
			});
			return cable;
		});
		this.on(events.TIMER_PLAY, this.onStart.bind(this));
	}

	init() {
		// drawCore
		const { coreWidth:h } = layout.cable;
		const pGemstone = `M0 ${h}L${h} 0L0 -${h}L-${h} 0Z`;

		this.createPathFromString(pGemstone)
			.shadow(layout.colors.strokeBg, 6)
			.fill(layout.colors.strokeBgL1)
			.z(10, 0)
			.build();
	}

	tick(now) {
		super.tick(now);

		// breath 动画
		const timer = this.root.scoreBoard.timer;
		if (!timer.isPlaying()) {
			return;
		}
		if (now - this.lastBreathTime >= 4000) {
			// 更新 lastBreathTime. 4 秒发一次 breath.
			this.lastBreathTime = now;
			this.cables.forEach(c => c.breath());
		}
	}

	onStart() {
		this.lastBreathTime = new Date().getTime();
	}
}

class Cable extends ZRenderComp {
	constructor(args) {
		super(args.parent);

		this.coreWidth = args.coreWidth;
		this.coreX = args.coreX;
		this.coreY = args.coreY;
		this.tagX = args.tagX;
		this.tagY = args.tagY;
		this.tagHeight = args.tagHeight;
		this.useParentZRenderInstance(this.coreX, this.coreY);

		this.pathFactory = args.pathFactory;
		this.playerNo = args.playerNo;
		this.phase = PHASE_PAUSED;

		this.on(events.PLAYER_START, this.onStart.bind(this));
		this.on(events.PLAYER_STOP, this.onPause.bind(this));
		this.on(events.PLAYER_FINISH, this.onStop.bind(this));
		this.on(events.PLAYER_RESET, this.onReset.bind(this));
	}

	init() {
		/** @type {string} */
		const pLine = this.pathFactory(
			this.coreWidth, this.coreX, this.coreY, this.tagX, this.tagY, this.tagHeight
		).join(' ');

		// 暗线 (当成 cable 的背景色)
		this.darkLine = this.createPathFromString(pLine)
			.fill(layout.colors.strokeBgL1)
			.opacity(0.8)
			.z(10, -10)
			.build();
		// 亮线 (激活时, 亮白色; 需要自动调节颜色, 在暗线、呼吸线之上)
		this.lightOpacity = 0.4;
		this.lightLine = this.createPathFromString(pLine)
			.fill(layout.colors.strokeBgL3)
			.opacity(0.4)
			.shadow(layout.colors.strokeBgL3, 5)
			.z(10, -8)
			.build();
		this.yellowOpacity = 0;
		this.yellowLine = this.createPathFromString(pLine)
			.fill(layout.colors.yellowNormal)
			.opacity(0)
			.shadow(layout.colors.yellowNormal, 5)
			.z(10, -8)
			.build();
		// 呼吸线白块 (动态效果, cable 含 clip, 在暗线之上、亮线之下)
		const grads = [
			{offset:0.34, color:'#FFF0'},
			{offset:0.42, color:'#FFF'},
			{offset:0.58, color:'#FFF'},
			{offset:0.66, color:'#FFF0'},
		];
		const [x, y] = this.relativePos();
		const width = layout.coreBg.width / 2;
		const gradX1 = (this.playerNo == 1 || this.playerNo == 4) ? 0.75 : 0.25;
		const gradX2 = (this.playerNo == 1 || this.playerNo == 4) ? 0.25 : 0.75;
		this.breathLine = this.createRect(width, width, -x / 2, -y / 2)
			.z(10, -9)
			.fillLinearGradient(gradX1, 0, gradX2, 1, grads)
			.opacity(0)
			.shadow('white', 5)
			.build();
		// 呼吸线 clip
		this.breathClip = this.createPathFromString(pLine)
			.opacity(0)
			.defineAsClip()
			.build();
		this.breathLine.setClipPath(this.breathClip);
	}

	breath() {
		const player = this.root.scoreBoard.findPlayer(this.playerNo);
		if (player.isFinished()) {
			return;
		}

		this.breathLine.show();
		let fromY, dy, deliverTime;
		switch (this.playerNo) {
		case 1: fromY = 0; dy = -800; deliverTime = 1000; break;
		case 2: fromY = 0; dy = -800; deliverTime = 800; break;
		case 3: fromY = -layout.coreBg.width / 2; dy = 800; deliverTime = 800; break;
		case 4: fromY = -layout.coreBg.width / 2; dy = 800; deliverTime = 1000; break;
		}

		let delivered = false;
		// 这个 anim 在 stop 时删除且让它失效  TODO
		this.createAnimation('breath.y')
			.whenUpdated(p => {
				this.breathLine.attr({ shape : { y : p.value }});
				if (!delivered && p.time >= deliverTime && this.phase == PHASE_RUNNING) {
					this.emit(events.BREATH_DELIVER, { playerNo : this.playerNo });
					delivered = true;
				}
			})
			.update()
			.when(0, fromY)
			.when(2000, fromY + dy).callback(() => this.breathLine.hide())
			.commit();
	}

	onStart(_, args) {
		if (this.playerNo != args.playerNo) {
			return;
		}
		this.phase = PHASE_RUNNING;
		this.showLightLine(false);
		this.showYellowLine(false);
		this.showBreathLine(true);
	}

	onPause(_, args) {
		if (this.playerNo != args.playerNo) {
			return;
		}
		this.phase = PHASE_PAUSED;
		this.showLightLine(true);
		this.showYellowLine(false);
		this.showBreathLine(false);
	}

	onStop(_, args) {
		if (this.playerNo != args.playerNo) {
			return;
		}
		this.phase = PHASE_FINISHED;
		this.showLightLine(false);
		this.showYellowLine(true);
		this.showBreathLine(false);
	}

	onReset(_, args) {
		if (this.playerNo != args.playerNo) {
			return;
		}
		this.phase = PHASE_PAUSED;
		this.showLightLine(true);
		this.showYellowLine(false);
		this.showBreathLine(false);
	}

	showLightLine(show) {
		const dst = show ? 0.4 : 0;
		if (this.lightOpacity == dst) {
			return;
		}
		this.createAnimation('light')
			.whenUpdated((p) => {
				this.lightLine.sp.attr({ style : { opacity : p.value } });
				this.lightOpacity = p.value;
			})
			.update()
			.when(0, this.lightOpacity)
			.when(500, dst)
			.commit();
	}

	showYellowLine(show) {
		if (this.yellowOpacity == 0 && !show) {
			return;
		}

		let el = this.createAnimation('yellow').whenUpdated((p) => {
			this.yellowLine.sp.attr({ style : { opacity : p.value } });
			this.yellowOpacity = p.value;
		});

		if (show) {
			el.update().when(0, 1).when(500, 0.3).commit();
		} else {
			el.update().when(0, this.yellowOpacity).when(500, 0).commit();
		}
	}

	showBreathLine(show) {
		this.breathLine.attr({
			style : { opacity : show ? 0.3 : 0 }
		});
		this.breathLine.hide();
	}
}

function createCableLTPath(coreWidth, coreX, coreY, tagX, tagY, tagHeight) {
	const l = 4; // lineWidth
	const l2 = l * 2; // lineWidth
	const ll = l / 2;
	const g = (coreWidth - 3 * l) / 2.5; // gapWidth
	const pLines = ['', '', ''];

	// 从中间向外: src, p1, p2, p3, dst
	// 中间的
	let srcX = coreX - 1.5 * g - 1.5 * l;
	let srcY = coreY;
	let dstX = tagX;
	let dstY = tagY + tagHeight / 2 + l2 + l;
	let p1X = srcX - coreWidth;
	let p1Y = srcY - coreWidth;
	let deltaX = p1X - dstX;
	const centerY0 = (p1Y + dstY) / 2;
	let centerY = centerY0;
	let p2X = p1X;
	let p2Y = centerY + deltaX / 2;
	let p3X = dstX;
	let p3Y = centerY - deltaX / 2;
	pLines[0] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l2}l-${l} -${l}v-${l2}L${dstX} ${dstY+ll}l${l+ll} -${l+ll}v${l2}l-${l} ${l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 左边的
	srcX = coreX - 2.5 * g - 2.5 * l;
	srcY = coreY;
	dstX = tagX - g - l;
	dstY = tagY + tagHeight / 2 + l2 - g;
	p1X = srcX - coreWidth;
	p1Y = srcY - coreWidth;
	deltaX = p1X - dstX;
	centerY = centerY0 + l2;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[1] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l2}l-${l} -${l}v-${l2}L${dstX+ll} ${dstY+l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 右边的
	srcX = coreX - 0.5 * g - 0.5 * l;
	srcY = coreY;
	dstX = tagX + g + l;
	dstY = tagY + tagHeight / 2 + l2 - g;
	p1X = srcX - coreWidth;
	p1Y = srcY - coreWidth;
	deltaX = p1X - dstX;
	centerY = centerY0 - l2;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[2] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l}l${l2} -${l2}v${l2}L${dstX+ll} ${dstY+l2}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	return pLines;
}

function createCableRTPath(coreWidth, coreX, coreY, tagX, tagY, tagHeight) {
	const l = 4; // lineWidth
	const l2 = l * 2; // lineWidth
	const ll = l / 2;
	const g = (coreWidth - 3 * l) / 2.5; // gapWidth
	const pLines = ['', '', ''];

	// 从中间向外: src, p1, p2, p3, dst
	// 中间的
	let srcX = coreX + 1.5 * g + 1.5 * l;
	let srcY = coreY;
	let dstX = tagX;
	let dstY = tagY + tagHeight / 2 + l2 + l;
	let p1X = srcX - coreWidth;
	let p1Y = srcY - coreWidth;
	let deltaX = dstX - p1X;
	const centerY0 = (p1Y + dstY) / 2;
	let centerY = centerY0;
	let p2X = p1X;
	let p2Y = centerY + deltaX / 2;
	let p3X = dstX;
	let p3Y = centerY - deltaX / 2;
	pLines[0] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l2}l-${l} -${l}v-${l2}L${dstX} ${dstY+ll}l${l+ll} -${l+ll}v${l2}l-${l} ${l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 左边的
	srcX = coreX + 0.5 * g + 0.5 * l;
	srcY = coreY;
	dstX = tagX - g - l;
	dstY = tagY + tagHeight / 2 + l2 - g;
	p1X = srcX - coreWidth;
	p1Y = srcY - coreWidth;
	deltaX = dstX - p1X;
	centerY = centerY0 + ll; // 间隙要小
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[1] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l2}l-${l} -${l}v-${l2}L${dstX+ll} ${dstY+l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 右边的
	srcX = coreX + 2.5 * g + 2.5 * l;
	srcY = coreY;
	dstX = tagX + g + l;
	dstY = tagY + tagHeight / 2 + l2 - g;
	p1X = srcX - coreWidth;
	p1Y = srcY - coreWidth;
	deltaX = dstX - p1X;
	centerY = centerY0 - ll;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[2] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY+l}l${l2} -${l2}v${l2}L${dstX+ll} ${dstY+l2}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	return pLines;
}

function createCableLBPath(coreWidth, coreX, coreY, tagX, tagY, tagHeight) {
	const l = 4; // lineWidth
	const l2 = l * 2; // lineWidth
	const ll = l / 2;
	const g = (coreWidth - 3 * l) / 2.5; // gapWidth
	const pLines = ['', '', ''];

	// 从中间向外: src, p1, p2, p3, dst
	// 中间的
	let srcX = coreX - 1.5 * g - 1.5 * l;
	let srcY = coreY;
	let dstX = tagX;
	let dstY = tagY - tagHeight / 2 - l2 - l;
	let p1X = srcX + coreWidth;
	let p1Y = srcY + coreWidth;
	let deltaX = dstX - p1X;
	const centerY0 = (p1Y + dstY) / 2;
	let centerY = centerY0;
	let p2X = p1X;
	let p2Y = centerY + deltaX / 2;
	let p3X = dstX;
	let p3Y = centerY - deltaX / 2;
	pLines[0] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l2}l-${l} ${l}v${l2}L${dstX} ${dstY-ll}l${l+ll} ${l+ll}v-${l2}l-${l} -${l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 左边的
	srcX = coreX - 2.5 * g - 2.5 * l;
	srcY = coreY;
	dstX = tagX - g - l;
	dstY = tagY - tagHeight / 2 - l2 + g;
	p1X = srcX + coreWidth;
	p1Y = srcY + coreWidth;
	deltaX = dstX - p1X;
	centerY = centerY0 + ll; // 间隙要小
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[1] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l2}l-${l} ${l}v${l2}L${dstX+ll} ${dstY-l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 右边的
	srcX = coreX - 0.5 * g - 0.5 * l;
	srcY = coreY;
	dstX = tagX + g + l;
	dstY = tagY - tagHeight / 2 - l2 + g;
	p1X = srcX + coreWidth;
	p1Y = srcY + coreWidth;
	deltaX = dstX - p1X;
	centerY = centerY0 - ll;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[2] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l}l${l2} ${l2}v-${l2}L${dstX+ll} ${dstY-l2}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	return pLines;
}

function createCableRBPath(coreWidth, coreX, coreY, tagX, tagY, tagHeight) {
	const l = 4; // lineWidth
	const l2 = l * 2; // lineWidth
	const ll = l / 2;
	const g = (coreWidth - 3 * l) / 2.5; // gapWidth
	const pLines = ['', '', ''];

	// 从中间向外: src, p1, p2, p3, dst
	// 中间的
	let srcX = coreX + 1.5 * g + 1.5 * l;
	let srcY = coreY;
	let dstX = tagX;
	let dstY = tagY - tagHeight / 2 - l2 - l;
	let p1X = srcX + coreWidth;
	let p1Y = srcY + coreWidth;
	let deltaX = p1X - dstX;
	const centerY0 = (p1Y + dstY) / 2;
	let centerY = centerY0;
	let p2X = p1X;
	let p2Y = centerY + deltaX / 2;
	let p3X = dstX;
	let p3Y = centerY - deltaX / 2;
	pLines[0] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l2}l-${l} ${l}v${l2}L${dstX} ${dstY-ll}l${l+ll} ${l+ll}v-${l2}l-${l} -${l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 左边的
	srcX = coreX + 0.5 * g + 0.5 * l;
	srcY = coreY;
	dstX = tagX - g - l;
	dstY = tagY - tagHeight / 2 - l2 + g;
	p1X = srcX + coreWidth;
	p1Y = srcY + coreWidth;
	deltaX = p1X - dstX;
	centerY = centerY0 + l2;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[1] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l2}l-${l} ${l}v${l2}L${dstX+ll} ${dstY-l}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	// 右边的
	srcX = coreX + 2.5 * g + 2.5 * l;
	srcY = coreY;
	dstX = tagX + g + l;
	dstY = tagY - tagHeight / 2 - l2 + g;
	p1X = srcX + coreWidth;
	p1Y = srcY + coreWidth;
	deltaX = p1X - dstX;
	centerY = centerY0 - l2;
	p2X = p1X;
	p2Y = centerY + deltaX / 2;
	p3X = dstX;
	p3Y = centerY - deltaX / 2;
	pLines[2] = `M${srcX-ll} ${srcY}L${p1X-ll} ${p1Y}L${p2X-ll} ${p2Y}L${p3X-ll} ${p3Y}`
			+ `L${dstX-ll} ${dstY-l}l${l2} ${l2}v-${l2}L${dstX+ll} ${dstY-l2}`
			+ `L${p3X+ll} ${p3Y}L${p2X+ll} ${p2Y}L${p1X+ll} ${p1Y}L${srcX+ll} ${srcY}z`;
	return pLines;
}

export {
	Cables
};
